package infoholders;
/**

 * This is the appointment class
 */

import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;

import people.Nurse;
import people.Patient;
import people.Person;
import utilities.Database;
import utilities.Serializer;


/**
 * Serves as a record keeper for when a patient's appointment is supposed to
 * occur, who their contact is, and a description of the appointment
 * 
 * @author William Hoffmann
 * 
 * @version $Revision: 1.0 $
 */
public class Appointment implements Serializable {

	/**
	 * id number of appointment corresponding to ID on databases
	 */
	private int id;
	/**
	 * Contact for this appointment
	 */
	private Person contact;

	/**
	 * The person who this appointment is for
	 */
	private Person patient;

	/**
	 * The beginning time of the appointment
	 */
	private Calendar myStartTime;

	/**
	 * The end time of the appointment
	 */
	private Calendar myEndTime;

	/**
	 * A description of what the appointment is for
	 */
	private String description;

	/**
	 * Constructor for an appointment. Takes a Nurse as a contact, a Patient for
	 * whom the appointment is for, a start time, an end time, and a
	 * description.
	 * 
	 * Throws an exception if the end time occurs before the star time
	 * @param myContact Nurse
	 * @param myPatient Patient
	 * @param myStartTime Calendar
	 * @param myEndTime Calendar
	 * @param description String
	
	 * @throws Exception throws an exception if myStartTime and myEndTime are
	 * null or if the start time occurs after the end time */
	public Appointment(Person patient, Person contact,
			Calendar myStartTime, Calendar myEndTime, String description) {
				
		this.patient = patient;
		this.contact = contact;
		this.myStartTime = myStartTime;
		this.myEndTime = myEndTime;
		this.description = description;
		
		if (myStartTime == null || myEndTime == null) {
			//TODO: create an exception
			System.err.println("myStartTime and myEndTime cannot be null");
			return;
		}
		// throw an error if the start time is after the end time
		if (myStartTime.compareTo(myEndTime) > 0) {
			//TODO: create an exception
			System.err.println("The start time must occur before the end time");
			return;
		}
		
		// create it in the database
		try {
			create();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * Sets a new contact for the patient
	 * 
	 * @param myContact
	 *            Nurse contact this appointment
	 */
	public void setContact(Person Contact) {
		this.contact = Contact;
	}

	/**
	 * Retrieves the contact for this appointment
	 * 
	
	 * @return the contact for this appointment */
	public Person getContact() {
		return contact;
	}

	/**
	 * Retrieves the patient whom this appointment is for
	 * 
	
	 * @return the Patient for this appointment */
	public Person getPatient() {
		return patient;
	}

	/**
	 * Sets the Patient contact for this appointment
	 * 
	 * @param myPatient
	 *            the Patient who this appointment is for
	 */
	public void setPatient(Person Patient) {
		this.patient = Patient;
	}

	/**
	 * Sets a new start time for this appointment
	 * 
	 * @param myStartTime
	 *            new start time for this appointment
	 */
	public void setMyStartTime(Calendar myStartTime) {
		this.myStartTime = myStartTime;
	}

	/**
	 * Retrieves the start time for this appointment
	 * 
	
	 * @return the start time for this appointment */
	public Calendar getMyStartTime() {
		return myStartTime;
	}

	/**
	 * Sets a new end time for this appointment
	 * 
	 * @param myEndTime
	 *            new end time for this appointment
	 */
	public void setMyEndTime(Calendar myEndTime) {
		this.myEndTime = myEndTime;
	}

	/**
	 * Retrieves the end time for this appointment
	 * 
	
	 * @return the end time for this appointment */
	public Calendar getMyEndTime() {
		return myEndTime;
	}

	/**
	 * Sets a new description for this appointment
	 * 
	 * @param description
	 *            new description for this appointment
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Retrieves the description for this appointment
	 * 
	
	 * @return the description for this appointment */
	public String getDescription() {
		return description;
	}

	/**
	 * Compares two appointments to see if they overlap
	 * 
	 * @param app
	 *            the appointment to compare this appointment with
	
	 * @return returns true if there is a conflict, false otherwise */
	public boolean hasConflict(Appointment app) {
		// An appointment does not conflict if the new start time
		// and new end time are before the current start time, or
		// after the current end time
		boolean isConflict = true;
		if (((this.getMyStartTime().compareTo(app.getMyStartTime()) < 0) && (this
				.getMyEndTime().compareTo(app.getMyStartTime()) < 0))
				|| ((this.getMyStartTime().compareTo(app.getMyEndTime()) > 0) && (this
						.getMyEndTime().compareTo(app.getMyEndTime()) > 0))) {

			isConflict = false;

		}
		return isConflict;
	}
	
	/**
	 * Returns the appointment as text
	 * 
	
	 * @return a String with all the appointment details */
	public String toString() {
		return "Patient name: " + patient.toString() + "Time: " + 
			myStartTime.toString() + " - " + myEndTime.toString() + 
			"\nDescription: " + description;
	}
	
	public void update() throws IOException {
		Database db = new Database();
		Connection conn = db.getConnection();
		
		try
		{
			Statement st = conn.createStatement();
			
			String patientUpdate = "UPDATE schedule SET patient = '" 
				+ patient.getUserID() + "' WHERE id='" + id + "'";
			String contactUpdate = "UPDATE schedule SET contact = '" 
				+ contact.getUserID() + "' WHERE id='" + id + "'";
			String startTimeUpdate = "UPDATE schedule SET start_time = \"" 
				+ Serializer.toString(myStartTime) + "\" WHERE id='" + id + "'";
			String endTimeUpdate = "UPDATE schedule SET end_time = \"" 
				+ Serializer.toString(myEndTime) + "\" WHERE id='" + id + "'";
			String descriptionUpdate = "UPDATE schedule SET description= \"" 
				+ description + "\" WHERE id='" + id + "'";
			
			st.executeUpdate(patientUpdate);
			st.executeUpdate(contactUpdate);
			st.executeUpdate(startTimeUpdate);
			st.executeUpdate(endTimeUpdate);
			st.executeUpdate(descriptionUpdate);
		}
		catch (SQLException ex)
		{
			System.err.println(ex.getMessage());
		} finally {
			db.closeConnection();
		}
	}
	public void create() throws IOException {
		Database db = new Database();
		Connection conn = db.getConnection();
		
		try
		{
			String sql = "INSERT INTO schedule(patient, contact, start_time, end_time, description) " +
							"VALUES (\"" + patient.getUserID() + "\",\"" 
							   + contact.getUserID() + "\", \"" 
							   + Serializer.toString(myStartTime) + "\",\"" 
							   + Serializer.toString(myEndTime) + "\",\"" 
							   + description + "\")";
						
			PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
			
			// execute the query
			stmt.execute();
			
			// get the generated id key
			ResultSet res = stmt.getGeneratedKeys();
			
			// set the generated id
			while (res.next()) {
			    setId(res.getInt(1));
			}
		}
		catch (SQLException ex)
		{
			ex.printStackTrace();
			System.err.println(ex.getMessage());
		} finally {
			db.closeConnection();
		}		
	}
	public void delete() {
		Database db = new Database();
		Connection conn = db.getConnection();
		try
		{
			Statement st = conn.createStatement();
			st.executeUpdate("DELETE FROM schedule WHERE id='"+id+"'");
		}
		catch (SQLException ex)
		{
			System.err.println(ex.getMessage());
		} finally {
			// close the connection
			db.closeConnection();
		}
	}
}
